Install R packages if needed.
# Required packages
required_packages <- c(
"rmarkdown",
"bookdown",
"knitr",
"lubridate",
"tidyverse",
"purrr",
"glue",
"lubridate",
"sf",
"tmap",
"leaflet",
"leaflet.extras"
)
# Try to install packages if not installed
default_options <- options()
tryCatch(
{
# Disable interactivity
options(install.packages.compile.from.source = "always")
# Install package if not installed
for (package in required_packages) {
is_package_installed <- require(package, character.only = TRUE)
if (!is_package_installed) {
cat(paste0("Installing package: ", package, "\n"))
install.packages(package)
} else {
cat(paste0("Package already installed: ", package, "\n"))
}
}
},
error = function(cond) {
stop(cond)
},
finally = {
options(default_options) # reset interactivity
}
)Load R libraries.
Read data from the data folder.
Bikeways data with manually verified (Google Street View/Earth and Web Search) painted lanes and cycle tracks for Toronto, Canada
# Read data
toronbike_raw <- read_sf("../../data/toronto-bikeways-2024-06-02.geojson")
# Get download date
toronbike_dldate <- ddesc %>% filter(
file == "toronto-bikeways-2024-06-02.geojson"
) %>% pull(download_date)Only the first 1000 records are shown.
The data contains the following columns:
## Simple feature collection with 1323 features and 22 fields
## Geometry type: MULTILINESTRING
## Dimension: XY
## Bounding box: xmin: -79.63039 ymin: 43.58221 xmax: -79.11803 ymax: 43.85546
## Geodetic CRS: WGS 84
## # A tibble: 1,323 × 23
## id street street_from street_to road_type road_type_recode install_year
## <chr> <chr> <chr> <chr> <chr> <chr> <dbl>
## 1 8 Bloor St… Parliament… Castle F… Major Ar… Arterial 2001
## 2 17 Lake Sho… Humber Bay… Humber B… Major Ar… Arterial 2001
## 3 18 Lake Sho… 37 M E Fle… Humber B… Major Ar… Arterial 2001
## 4 19 Lake Sho… 50.7 M E L… 37 M E F… Major Ar… Arterial 2001
## 5 38 Queens Q… Martin Goo… Bathurst… Collector Collector 2001
## 6 39 Davenpor… Cottingham… Macphers… Minor Ar… Arterial 2001
## 7 40 Elizabet… College St Gerrard … Collector Collector 2001
## 8 41 Gerrard … Yonge St Church St Minor Ar… Arterial 2001
## 9 42 Macphers… Davenport … Poplar P… Collector Collector 2001
## 10 43 Lake Sho… Marine Par… Palace P… Major Ar… Arterial 2001
## # ℹ 1,313 more rows
## # ℹ 16 more variables: install_type <chr>, verify_install_year <dbl>,
## # verify_install_date <chr>, verify_install_type <chr>,
## # verify_install_comment <chr>, verify_upgrade1_year <dbl>,
## # verify_upgrade1_date <chr>, verify_upgrade1_type <chr>,
## # verify_upgrade1_comment <chr>, verify_upgrade2_year <dbl>,
## # verify_upgrade2_date <chr>, verify_upgrade2_type <chr>, …
The data files are available below:
The verification dates manually entered for the cycling infrastructure data were unstructured and do not follow a structured format suitable for analysis.
Nevan Opp nevanopp@cmail.carleton.ca went through the dates in Google Sheets, interpreted them, and formatted them into structured dates, while Richard Wen richard.wen@utoronto.ca updated and fixed errors as needed.
These structured dates can then be joined back to the unstructured dates to include higher resolution temporal data to the cycling infrastructure install and upgrade dates.
# Read data
vdates_raw <- read_csv("../../data/verify-dates-2024-06-12.csv")
# Get download date
vdates_dldate <- ddesc %>% filter(
file == "verify-dates-2024-06-12.csv"
) %>% pull(download_date)The data contains the following columns:
The data files are available below:
Filter out empty install/upgrade types.
# Filter out none or na
toronbike <- toronbike_raw %>%
filter(
!verify_install_type %in% c("None", NA) |
!verify_upgrade1_type %in% c("None", NA) |
!verify_upgrade2_type %in% c("None", NA)
)
# Display non empty types in at least one of install or upgrade
toronbike %>%
as_tibble %>%
select(-geometry) %>%
select(
id,
verify_install_type,
verify_upgrade1_type,
verify_upgrade2_type
)Add cleaned post-2011 dates to verified bikeways.
# Add cleaned post-2011 dates to bikeways
toronbike <- toronbike %>%
left_join( # clean install dates
vdates_raw %>%
rename_all(~str_replace(., "verify_", "clean_install_")),
by = join_by(verify_install_date == clean_install_date_raw)
) %>%
left_join( # clean upgrade1 dates
vdates_raw %>%
rename_all(~str_replace(., "verify_", "clean_upgrade1_")),
by = join_by(verify_upgrade1_date == clean_upgrade1_date_raw)
) %>%
left_join( # clean upgrade2 dates
vdates_raw %>%
rename_all(~str_replace(., "verify_", "clean_upgrade2_")),
by = join_by(verify_upgrade2_date == clean_upgrade2_date_raw)
)
# Display cleaned dates columns
toronbike %>%
as_tibble %>%
select(-geometry) %>%
select(id, verify_install_date, verify_upgrade1_date, verify_upgrade2_date, starts_with("clean_"))Assign semesters to each bikeway date, where a value of:
1: represents November (this year) to April of next
year2: represents May to October of next year# Add semesters to bike based on clean dates
toronbike <- toronbike %>%
mutate(
clean_install_semester = case_when( # install semester
month(clean_install_date) %in% c(11:12, 1:4) |
(
month(clean_install_date_start) %in% c(11:12, 1:4) &
( # Nov to Dec of this year
month(clean_install_date_end) %in% 11:12 &
year(clean_install_date_end) == year(clean_install_date_start)
) |
( # Jan to Apr of this or next year
month(clean_install_date_end) %in% 1:4 &
year(clean_install_date_end) == year(clean_install_date_start) |
year(clean_install_date_end) == (year(clean_install_date_start) + 1)
)
) ~ 2, # Nov to Apr of next year
month(clean_install_date) %in% 5:10 |
(
month(clean_install_date_start) %in% 5:10 &
month(clean_install_date_end) %in% 5:10 &
year(clean_install_date_start) == year(clean_install_date_end)
) ~ 1 # May to Oct
),
clean_upgrade1_semester = case_when( # upgrade1 semester
month(clean_upgrade1_date) %in% c(11:12, 1:4) |
(
month(clean_upgrade1_date_start) %in% c(11:12, 1:4) &
( # Nov to Dec of this year
month(clean_upgrade1_date_end) %in% 11:12 &
year(clean_upgrade1_date_end) == year(clean_upgrade1_date_start)
) |
( # Jan to Apr of this or next year
month(clean_upgrade1_date_end) %in% 1:4 &
year(clean_upgrade1_date_end) == year(clean_upgrade1_date_start) |
year(clean_upgrade1_date_end) == (year(clean_upgrade1_date_start) + 1)
)
) ~ 2, # Nov to Apr of next year
month(clean_upgrade1_date) %in% 5:10 |
(
month(clean_upgrade1_date_start) %in% 5:10 &
month(clean_upgrade1_date_end) %in% 5:10 &
year(clean_upgrade1_date_start) == year(clean_upgrade1_date_end)
) ~ 1 # May to Oct
),
clean_upgrade2_semester = case_when( # upgrade2 semester
month(clean_upgrade2_date) %in% c(11:12, 1:4) |
(
month(clean_upgrade2_date_start) %in% c(11:12, 1:4) &
( # Nov to Dec of this year
month(clean_upgrade2_date_end) %in% 11:12 &
year(clean_upgrade2_date_end) == year(clean_upgrade2_date_start)
) |
( # Jan to Apr of this or next year
month(clean_upgrade2_date_end) %in% 1:4 &
year(clean_upgrade2_date_end) == year(clean_upgrade2_date_start) |
year(clean_upgrade2_date_end) == (year(clean_upgrade2_date_start) + 1)
)
) ~ 2, # Nov to Apr of next year
month(clean_upgrade2_date) %in% 5:10 |
(
month(clean_upgrade2_date_start) %in% 5:10 &
month(clean_upgrade2_date_end) %in% 5:10 &
year(clean_upgrade2_date_start) == year(clean_upgrade2_date_end)
) ~ 1 # May to Oct
)
)
# Display semesters
toronbike %>%
as_tibble %>%
select(-geometry) %>%
select(
id,
clean_install_date,
clean_install_date_start,
clean_install_date_end,
clean_install_semester,
clean_upgrade1_date,
clean_upgrade1_date_start,
clean_upgrade1_date_end,
clean_upgrade1_semester,
clean_upgrade2_date,
clean_upgrade2_date_start,
clean_upgrade2_date_end,
clean_upgrade2_semester
)Explore accuracy of Toronto bikeway data compared.
Inspect all bikeways where the original installation year is not equal to the verified installation year.
# Filter bike for unmatched install year and add diff in years
toronbike_instyearx <- toronbike %>%
filter(
install_year != verify_install_year &
!verify_install_type %in% c("None", NA)
) %>%
mutate(
verify_install_year_diff = verify_install_year - install_year
) %>%
relocate(
install_year,
verify_install_year,
verify_install_year,
verify_install_year_diff,
install_type,
verify_install_type,
.after = street_to
)# Map bike with unmatched install years
tmap_mode("view")
toronbike_instyearx_map <- tm_basemap("CartoDB.Positron") +
tm_shape(
toronbike_instyearx %>%
select(!ends_with("_comment")) %>%
st_buffer(25),
name = "Install with Inaccurate Year"
) +
tm_polygons(
col = "verify_install_year_diff",
border.col = NULL,
popup.vars = T
)
# Add fullscreen control to map
tmap_leaflet(toronbike_instyearx_map) %>%
addFullscreenControl()# Save unmatched install year bike csv
toronbike_instyearx %>%
mutate(geometry_wkb = st_as_text(geometry)) %>%
select(-geometry) %>%
write_sf("../../data/archive/toronto-bikeways-instyearx-2024-06-02.csv", na = "", append = F)
# Save unmatched bike install year geojson
toronbike_instyearx %>%
write_sf("../../data/archive/toronto-bikeways-instyearx-2024-06-02.geojson", na = "", append = F)
# Display bike with unmatched years
toronbike_instyearx %>%
as_tibble %>%
select(-geometry)Inspect post-2011 bikeways where segments had no semester assigned.
# Filter bike for post-2011 and no semester
toronbike_nosemesterp2011 <- toronbike %>%
filter( # post-2011
verify_install_year > 2011 |
verify_upgrade1_year > 2011 |
verify_upgrade2_year > 2011
) %>%
filter( # no semester
is.na(clean_install_semester) |
is.na(clean_upgrade1_semester) |
is.na(clean_upgrade2_semester)
) %>%
relocate(
verify_install_year,
verify_install_date,
clean_install_date_start,
clean_install_date_end,
clean_install_semester,
verify_upgrade1_year,
verify_upgrade1_date,
clean_upgrade1_date_start,
clean_upgrade1_date_end,
clean_upgrade1_semester,
verify_upgrade2_year,
verify_upgrade2_date,
clean_upgrade2_date_start,
clean_upgrade2_date_end,
clean_upgrade2_semester,
.after = street_to
)
# Assign base cols for map
nosemester_cols <- c(
"id",
"street",
"street_from",
"street_to"
)
# Filter post-2011 install with no semesters
toronbike_noseminstp2011 <- toronbike_nosemesterp2011 %>%
select(
all_of(nosemester_cols),
starts_with("install"),
starts_with("verify_install"),
starts_with("clean_install")
) %>%
filter(
is.na(clean_install_semester) &
verify_install_year > 2011 &
!verify_install_type %in% c("None", NA)
)
# Filter post-2011 upgrade1 with no semesters
toronbike_nosemu1p2011 <- toronbike_nosemesterp2011 %>%
select(
all_of(nosemester_cols),
starts_with("upgrade1"),
starts_with("verify_upgrade1"),
starts_with("clean_upgrade1")
) %>%
filter(
is.na(clean_upgrade1_semester) &
verify_upgrade1_year > 2011 &
!verify_upgrade1_type %in% c("None", NA)
)
# Filter post-2011 upgrade2 with no semesters
toronbike_nosemu2p2011 <- toronbike_nosemesterp2011 %>%
select(
all_of(nosemester_cols),
starts_with("upgrade2"),
starts_with("verify_upgrade2"),
starts_with("clean_upgrade2")
) %>%
filter(
is.na(clean_upgrade2_semester) &
verify_upgrade2_year > 2011 &
!verify_upgrade2_type %in% c("None", NA)
)# Map bike with unmatched install years
tmap_mode("view")
toronbike_nosemester_map <- tm_basemap("CartoDB.Positron") +
tm_shape(
toronbike_noseminstp2011 %>%
select(!ends_with("_comment")) %>%
st_buffer(25),
name = "Install (Green)"
) +
tm_polygons(
col = "green",
border.col = "green",
popup.vars = T
) +
tm_shape(
toronbike_nosemu1p2011 %>%
select(!ends_with("_comment")) %>%
st_buffer(25),
name = "1st Upgrade (Orange)"
) +
tm_polygons(
col = "orange",
border.col = "orange",
popup.vars = T
) +
tm_shape(
toronbike_nosemu2p2011 %>%
select(!ends_with("_comment")) %>%
st_buffer(25),
name = "2nd Upgrade (Red)"
) +
tm_polygons(
col = "red",
border.col = "red",
popup.vars = T
)
# Add fullscreen control to map
tmap_leaflet(toronbike_nosemester_map) %>%
addFullscreenControl()# Save post2011 no semester install csv
toronbike_noseminstp2011 %>%
mutate(geometry_wkb = st_as_text(geometry)) %>%
select(-geometry) %>%
write_sf("../../data/archive/toronto-bikeways-noseminstp2011-2024-06-02.csv", na = "", append = F)
# Save post2011 no semester install geojson
toronbike_noseminstp2011 %>%
write_sf("../../data/archive/toronto-bikeways-noseminstp2011-2024-06-02.geojson", na = "", append = F)
# Display data
toronbike_noseminstp2011 %>%
as_tibble %>%
select(-geometry)# Save post2011 no semester upgrade1 csv
toronbike_nosemu1p2011 %>%
mutate(geometry_wkb = st_as_text(geometry)) %>%
select(-geometry) %>%
write_sf("../../data/archive/toronto-bikeways-nosemu1p2011-2024-06-02.csv", na = "", append = F)
# Save post2011 no semester upgrade1 geojson
toronbike_nosemu1p2011 %>%
write_sf("../../data/archive/toronto-bikeways-nosemu1p2011-2024-06-02.geojson", na = "", append = F)
# Display data
toronbike_nosemu1p2011 %>%
as_tibble %>%
select(-geometry)# Save post2011 no semester upgrade2 csv
toronbike_nosemu2p2011 %>%
mutate(geometry_wkb = st_as_text(geometry)) %>%
select(-geometry) %>%
write_sf("../../data/archive/toronto-bikeways-nosemu2p2011-2024-06-02.csv", na = "", append = F)
# Save post2011 no semester upgrade2 geojson
toronbike_nosemu2p2011 %>%
write_sf("../../data/archive/toronto-bikeways-nosemu2p2011-2024-06-02.geojson", na = "", append = F)
# Display data
toronbike_nosemu2p2011 %>%
as_tibble %>%
select(-geometry)